package u16888

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"time"

	"github.com/astaxie/beego/logs"
	"github.com/robertkrimen/otto"

	"lottery/models"
)

var gameDataJs = `
data = %s;
realNode = data[3];
leagueNameNodes = realNode[0];
gameNodes = realNode[1];
handicapNodes = realNode[2];
gameDataNodes = realNode[5];

leagueGames = [];
for (index in leagueNameNodes) {
    leagueGames.push({
        "id": leagueNameNodes[index][0],
        "name": leagueNameNodes[index][1],
    })
}
leagueGamesStr = JSON.stringify(leagueGames);

games = [];
for (index in gameNodes) {
    games.push({
        "id": gameNodes[index][0],
        "leagueId": gameNodes[index][2],
        "hName": gameNodes[index][3],
        "aName": gameNodes[index][4],
        "playTime": gameNodes[index][7],
    })
}

gameStr = JSON.stringify(games);

findGame = function(handicapId) {
    for (index in handicapNodes) {
        handicapNode = handicapNodes[index]
        if (handicapNode[0] == handicapId && handicapNode[2] == 0) {
            return handicapNode
        }
    }

    return null;
}

gameDatas = [];
for (index in gameDataNodes) {
    gameDataNode = gameDataNodes[index];
    game = findGame(gameDataNode[1][0]);
    if (game == null) {
        continue;
    }

    gameDatas.push({
        "handicapId": gameDataNode[0],
        "handicap": gameDataNode[1][4],
        "handicapType": gameDataNode[1][1],
        "gameId": game[1],
        "hScore": game[3],
        "aScore": game[4],
        "hRate": gameDataNode[2][0],
        "hIndicator": 1,
        "aRate": gameDataNode[2][1],
        "aIndicator": 2,
    });
}

gameDataStr = JSON.stringify(gameDatas);
`
var handicapTypeMap map[int]int

func init() {
	handicapTypeMap = make(map[int]int)
	handicapTypeMap[1] = 1
	handicapTypeMap[3] = 2
	handicapTypeMap[7] = 3
	handicapTypeMap[9] = 4
}

func (u *U16888) getRawGameData() (data []byte, err error) {
	reqUrl := fmt.Sprintf("http://%s/web-root/restricted/odds-display/today-data.aspx?od-param=1,1,1,1,1,2,2,2,3,1&fi=0", u.hostName)
	httpReq, err := http.NewRequest("GET", reqUrl, nil)
	if err != nil {
		return
	}

	httpReq.Header = make(http.Header)
	refererUrl := fmt.Sprintf("http://%s/web-root/restricted/default.aspx?loginname=%s&redirect=true", u.hostName, u.loginName)
	httpReq.Header.Set("Referer", refererUrl)
	httpReq.Header.Set("User-Agent", u.ua)

	httpResp, err := u.client.Do(httpReq)
	if err != nil {
		return
	}
	defer httpResp.Body.Close()

	data, err = ioutil.ReadAll(httpResp.Body)
	if err != nil {
		return
	}
	return
}

func (u *U16888) getGameData() (games []*models.Game, gameDatas []*models.GameData) {
	start := time.Now()
	data, err := u.getRawGameData()
	if err != nil {
		return
	}

	games, gameDatas, err = u.parseGameData(data)
	if err != nil {
		logs.Warn("parseGameData %s", err.Error())
	}

	end := time.Now()
	logs.Debug("u16888 getGameData use time:%d mill sec", (end.UnixNano()-start.UnixNano())/int64(time.Millisecond))
	return
}

func (u *U16888) parseGameData(data []byte) (games []*models.Game, gameDatas []*models.GameData, err error) {
	leftIndex := bytes.Index(data, []byte("["))
	rightIndex := len(");")
	if leftIndex == -1 {
		return
	}

	if len(data) <= (leftIndex + rightIndex) {
		return
	}

	data = data[leftIndex : len(data)-rightIndex]

	js := fmt.Sprintf(gameDataJs, string(data))
	vm := otto.New()
	_, err = vm.Run(js)
	if err != nil {
		logs.Warn("run js data:%s err:%s", string(data), err.Error())
		return
	}

	leagueGames := make([]*LeagueGame, 0, 50)
	if err = u.parseRawData(vm, "leagueGamesStr", &leagueGames); err != nil {
		return
	}

	findLeagueGameName := func(leagueId int64) string {
		for _, leagueGame := range leagueGames {
			if leagueGame.Id == leagueId {
				return leagueGame.Name
			}
		}
		return ""
	}

	ugames := make([]*UGame, 0, 10)
	if err = u.parseRawData(vm, "gameStr", &ugames); err != nil {
		return
	}

	format := "01/02/2006 15:04"
	games = make([]*models.Game, 0, 10)
	for _, ugame := range ugames {
		game := &models.Game{
			LeagueGameId:   strconv.FormatInt(ugame.LeagueId, 10),
			LeagueGameName: findLeagueGameName(ugame.LeagueId),
			PlatformGameId: strconv.FormatInt(ugame.Id, 10),
			HName:          ugame.HName,
			AName:          ugame.AName,
			PlayTime:       ugame.PlayTime,
		}

		startTime, err := time.ParseInLocation(format, ugame.PlayTime, time.Local)
		if err == nil {
			game.StartTime = startTime.UnixNano() / int64(time.Millisecond)
		}
		games = append(games, game)
	}

	ugameDatas := make([]*UGameData, 0, 10)
	if err = u.parseRawData(vm, "gameDataStr", &ugameDatas); err != nil {
		return
	}

	createTime := time.Now()
	gameDatas = make([]*models.GameData, 0, 100)
	for _, ugameData := range ugameDatas {
		handicapType, ok := handicapTypeMap[ugameData.HandicapType]
		if !ok {
			continue
		}

		gameData := &models.GameData{
			PlatformGameId: strconv.FormatInt(ugameData.GameId, 10),
			HandicapId:     strconv.FormatInt(ugameData.HandicapId, 10),
			Handicap:       ugameData.Handicap,
			HRate:          ugameData.HRate,
			HIndicator:     ugameData.HIndicator,
			ARate:          ugameData.ARate,
			AIndicator:     ugameData.AIndicator,
			HScore:         ugameData.HScore,
			AScore:         ugameData.AScore,
			HandicapType:   handicapType,
			AgentId:        u.agentInfo.Id,
			CreateTime:     createTime.UnixNano() / int64(time.Millisecond),
		}

		if handicapType == 1 || handicapType == 3 {
			if gameData.HRate < 0 {
				// 主队上盘
				gameData.Handicap = -gameData.Handicap
			}
		}

		// if rate, err := u.getTickRate(1, gameData); err == nil {
		// 	gameData.HRate = rate
		// }

		// if rate, err := u.getTickRate(2, gameData); err == nil {
		// 	gameData.ARate = rate
		// }

		gameDatas = append(gameDatas, gameData)
	}
	return
}

func (u *U16888) getTickRate(team int, gameData *models.GameData) (rate float64, err error) {
	op := "h"
	rate = gameData.HRate
	if team == 2 {
		op = "a"
		rate = gameData.ARate
	}

	odds := fmt.Sprintf("%0.2f", rate)
	tickReqUrl := fmt.Sprintf("http://%s/web-root/restricted/ticket/ticket.aspx?loginname=%s&id=%s&op=%s&odds=%s&hdpType=1&isor=0&isLive=0&betpage=18&style=1",
		u.hostName, u.loginName, gameData.HandicapId, op, odds)

	tickReq, _ := http.NewRequest("GET", tickReqUrl, nil)
	refererUrl := fmt.Sprintf("http://%s/web-root/restricted/default.aspx?loginname=%s&redirect=true", u.hostName, u.loginName)
	tickReq.Header.Set("Referer", refererUrl)
	tickReq.Header.Set("User-Agent", u.ua)
	tickResp, err := u.client.Do(tickReq)
	if err != nil {
		logs.Warn("tick req err: %s", err.Error())
		return
	}

	defer tickResp.Body.Close()
	data, err := ioutil.ReadAll(tickResp.Body)
	if err != nil {
		logs.Warn("tick resp %s", string(data))
		return
	}

	leftIndex := bytes.IndexByte(data, '[')
	if leftIndex != -1 {
		rightIndex := bytes.LastIndexByte(data, ']')
		data = data[leftIndex : rightIndex+1]
		vm, _, err := otto.Run(fmt.Sprintf(tickJs, string(data)))
		if err != nil {
			return 0, err
		}

		rateValue, err := vm.Get("rate")
		if err != nil {
			return 0, err
		}

		rateStr := rateValue.String()
		rate, err = strconv.ParseFloat(rateStr, 64)
		return rate, err
	}
	return
}

func (u *U16888) parseRawData(vm *otto.Otto, key string, v interface{}) (err error) {
	value, err := vm.Get(key)
	if err != nil {
		return
	}

	err = json.Unmarshal([]byte(value.String()), v)
	return
}
